

#ifndef _TCP_SERVER_H_
#define _TCP_SERVER_H_

#include "Callbacks.hpp"
#include "TcpConnection.hpp"
#include "noncopyable.hpp"
#include <atomic>
#include <memory>
#include <string>
#include <unordered_map>

namespace zephyr {

class Acceptor;
class EventLoop;
class EventLoopThreadPool;

class TcpServer : noncopyable {
  public:
    using ThreadInitCallback = std::function<void(EventLoop *)>;
    enum Option {
        NoReusePort = 0,
        ReusePort = 1
    };

    TcpServer(EventLoop *loop, const InetAddress &listenaddr, const std::string &name, Option = NoReusePort);
    ~TcpServer();

    void setThreadInitCallback(const ThreadInitCallback &cb) { m_threadInitCallback = cb; }
    void setConnectionCallback(const ConnectionCallback &cb) { m_connectionCallback = cb; }
    void setMessageCallback(const MessageCallback &cb) { m_messageCallback = cb; }
    void setWriteCompleteCallback(const WriteCompleteCallback &cb) { m_writeCompletCallback = cb; }

    void setThreadNum(int numThreads);
    void start();

  private:
    // new tcpconnection
    void newConnection(int sockfd, const InetAddress &peeraddr);
    void removeConnection(const TcpConnectionPtr &conn);

    void removeConnectionInLoop(const TcpConnectionPtr &conn);

    using ConnectionMap = std::unordered_map<std::string, TcpConnectionPtr>;

    EventLoop *m_loop;

    const std::string m_ipPort;
    const std::string m_name;

    std::shared_ptr<Acceptor> m_acceptor;
    std::shared_ptr<EventLoopThreadPool> m_threadpool;

    ConnectionCallback m_connectionCallback;
    MessageCallback m_messageCallback;
    WriteCompleteCallback m_writeCompletCallback;

    ThreadInitCallback m_threadInitCallback;

    std::atomic_int m_started;
    int m_nextConnid;
    ConnectionMap m_connections;
};

}

#endif // _TCP_SERVER_H_